Beispiel #1
0
 def _draw_rings(self, dr: svgwrite.Drawing, g: svgwrite.container.Group,
                 center: XY, radius_range: ValueRange) -> None:
     length_range = self.poster.length_range_by_date
     if not length_range.is_valid():
         return
     min_length = length_range.lower()
     max_length = length_range.upper()
     assert min_length is not None
     assert max_length is not None
     ring_distance = self._determine_ring_distance(max_length)
     if ring_distance is None:
         return
     distance = ring_distance
     while distance < max_length:
         radius = radius_range.interpolate(
             (distance / max_length).magnitude)
         g.add(
             dr.circle(
                 center=center.tuple(),
                 r=radius,
                 stroke=self._ring_color,
                 stroke_opacity="0.2",
                 fill="none",
                 stroke_width=0.3,
             ))
         distance += ring_distance
Beispiel #2
0
 def _draw_rings(self, dr: svgwrite.Drawing, center: XY, radius_range: ValueRange):
     length_range = self.poster.length_range_by_date
     ring_distance = self._determine_ring_distance()
     if ring_distance is None:
         return
     distance = ring_distance
     while distance < length_range.upper():
         radius = (
             radius_range.lower()
             + radius_range.diameter() * distance / length_range.upper()
         )
         dr.add(
             dr.circle(
                 center=center.tuple(),
                 r=radius,
                 stroke=self._ring_color,
                 stroke_opacity="0.2",
                 fill="none",
                 stroke_width=0.3,
             )
         )
         distance += ring_distance
    def _draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group,
              size: XY, offset: XY, year: int) -> None:
        min_size = min(size.x, size.y)
        year_size = min_size * 4.0 / 80.0
        year_style = f"font-size:{year_size}px; font-family:Arial;"
        month_style = f"font-size:{min_size * 3.0 / 80.0}px; font-family:Arial;"
        day_style = f"dominant-baseline: central; font-size:{min_size * 1.0 / 80.0}px; font-family:Arial;"
        day_length_style = f"font-size:{min_size * 1.0 / 80.0}px; font-family:Arial;"

        g.add(
            dr.text(
                f"{year}",
                insert=offset.tuple(),
                fill=self.poster.colors["text"],
                alignment_baseline="hanging",
                style=year_style,
            ))
        offset.y += year_size
        size.y -= year_size
        count_x = 31
        for month in range(1, 13):
            date = datetime.date(year, month, 1)
            (_, last_day) = calendar.monthrange(year, month)
            count_x = max(count_x, date.weekday() + last_day)

        cell_size = min(size.x / count_x, size.y / 36)
        spacing = XY(
            (size.x - cell_size * count_x) / (count_x - 1),
            (size.y - cell_size * 3 * 12) / 11,
        )

        for month in range(1, 13):
            date = datetime.date(year, month, 1)
            y = month - 1
            y_pos = offset.y + (y * 3 + 1) * cell_size + y * spacing.y
            g.add(
                dr.text(
                    self.poster.month_name(month),
                    insert=(offset.x, y_pos - 2),
                    fill=self.poster.colors["text"],
                    alignment_baseline="hanging",
                    style=month_style,
                ))

            day_offset = date.weekday()
            while date.month == month:
                x = date.day - 1
                x_pos = offset.x + (day_offset + x) * cell_size + x * spacing.x
                pos = (x_pos + 0.05 * cell_size, y_pos + 1.15 * cell_size)
                dim = (cell_size * 0.9, cell_size * 0.9)
                text_date = date.strftime("%Y-%m-%d")
                if text_date in self.poster.tracks_by_date:
                    tracks = self.poster.tracks_by_date[text_date]
                    length = sum([t.length() for t in tracks])
                    has_special = len([t for t in tracks if t.special]) > 0
                    color = self.color(self.poster.length_range_by_date,
                                       length, has_special)
                    g.add(dr.rect(pos, dim, fill=color))
                    g.add(
                        dr.text(
                            utils.format_float(self.poster.m2u(length)),
                            insert=(
                                pos[0] + cell_size / 2,
                                pos[1] + cell_size + cell_size / 2,
                            ),
                            text_anchor="middle",
                            style=day_length_style,
                            fill=self.poster.colors["text"],
                        ))
                else:
                    g.add(dr.rect(pos, dim, fill="#444444"))

                g.add(
                    dr.text(
                        localized_day_of_week_name(date.weekday(), short=True),
                        insert=(
                            offset.x + (day_offset + x) * cell_size +
                            cell_size / 2,
                            pos[1] + cell_size / 2,
                        ),
                        text_anchor="middle",
                        alignment_baseline="middle",
                        style=day_style,
                    ))
                date += datetime.timedelta(1)
    def draw(self, dr: svgwrite.Drawing, g: svgwrite.container.Group, size: XY,
             offset: XY) -> None:
        if self.poster.tracks is None:
            raise PosterError("No tracks to draw")
        year_size = 200 * 4.0 / 80.0
        year_style = f"font-size:{year_size}px; font-family:Arial;"
        year_length_style = f"font-size:{110 * 3.0 / 80.0}px; font-family:Arial;"
        month_names_style = "font-size:2.5px; font-family:Arial"
        total_length_year_dict = self.poster.total_length_year_dict
        for year in self.poster.years.iter():
            g_year = dr.g(id=f"year{year}")
            g.add(g_year)

            start_date_weekday, _ = calendar.monthrange(year, 1)
            github_rect_first_day = datetime.date(year, 1, 1)
            # Github profile the first day start from the last Monday of the last year or the first Monday of this year
            # It depands on if the first day of this year is Monday or not.
            github_rect_day = github_rect_first_day + datetime.timedelta(
                -start_date_weekday)
            year_length = total_length_year_dict.get(year, 0)
            year_length_str = utils.format_float(self.poster.m2u(year_length))
            month_names = [
                locale.nl_langinfo(day)[:3]  # Get only first three letters
                for day in [
                    locale.MON_1,
                    locale.MON_2,
                    locale.MON_3,
                    locale.MON_4,
                    locale.MON_5,
                    locale.MON_6,
                    locale.MON_7,
                    locale.MON_8,
                    locale.MON_9,
                    locale.MON_10,
                    locale.MON_11,
                    locale.MON_12,
                ]
            ]
            km_or_mi = self.poster.u()
            g_year.add(
                dr.text(
                    f"{year}",
                    insert=offset.tuple(),
                    fill=self.poster.colors["text"],
                    alignment_baseline="hanging",
                    style=year_style,
                ))

            g_year.add(
                dr.text(
                    f"{year_length_str} {km_or_mi}",
                    insert=(offset.tuple()[0] + 165, offset.tuple()[1] + 2),
                    fill=self.poster.colors["text"],
                    alignment_baseline="hanging",
                    style=year_length_style,
                ))
            # add month name up to the poster one by one because of svg text auto trim the spaces.
            for num, name in enumerate(month_names):
                g_year.add(
                    dr.text(
                        f"{name}",
                        insert=(offset.tuple()[0] + 15.5 * num,
                                offset.tuple()[1] + 14),
                        fill=self.poster.colors["text"],
                        style=month_names_style,
                    ))

            rect_x = 10.0
            dom = (2.6, 2.6)
            # add every day of this year for 53 weeks and per week has 7 days
            for _i in range(54):
                rect_y = offset.y + year_size + 2
                for _j in range(7):
                    if int(github_rect_day.year) > year:
                        break
                    rect_y += 3.5
                    color = "#444444"
                    date_title = str(github_rect_day)
                    if date_title in self.poster.tracks_by_date:
                        tracks = self.poster.tracks_by_date[date_title]
                        length = sum([t.length() for t in tracks])
                        distance1 = self.poster.special_distance[
                            "special_distance"]
                        distance2 = self.poster.special_distance[
                            "special_distance2"]
                        has_special = distance1 < length < distance2
                        color = self.color(self.poster.length_range_by_date,
                                           length, has_special)
                        if length >= distance2:
                            special_color = self.poster.colors.get(
                                "special2") or self.poster.colors.get(
                                    "special")
                            if special_color is not None:
                                color = special_color
                        str_length = utils.format_float(
                            self.poster.m2u(length))
                        date_title = f"{date_title} {str_length} {km_or_mi}"

                    rect = dr.rect((rect_x, rect_y), dom, fill=color)
                    rect.set_desc(title=date_title)
                    g_year.add(rect)
                    github_rect_day += datetime.timedelta(1)
                rect_x += 3.5
            offset.y += 3.5 * 9 + year_size + 1.5
    def _draw(self, dr: svgwrite.Drawing, size: XY, offset: XY, year: int):
        min_size = min(size.x, size.y)
        year_size = min_size * 4.0 / 80.0
        year_style = f"font-size:{year_size}px; font-family:Arial;"
        month_style = f"font-size:{min_size * 3.0 / 80.0}px; font-family:Arial;"
        day_style = f"dominant-baseline: central; font-size:{min_size * 1.0 / 80.0}px; font-family:Arial;"
        day_length_style = f"font-size:{min_size * 1.0 / 80.0}px; font-family:Arial;"

        dr.add(
            dr.text(
                f"{year}",
                insert=offset.tuple(),
                fill=self.poster.colors["text"],
                alignment_baseline="hanging",
                style=year_style,
            )
        )
        offset.y += year_size
        size.y -= year_size
        count_x = 31
        for month in range(1, 13):
            date = datetime.date(year, month, 1)
            (_, last_day) = calendar.monthrange(year, month)
            count_x = max(count_x, date.weekday() + last_day)

        cell_size = min(size.x / count_x, size.y / 36)
        spacing = XY(
            (size.x - cell_size * count_x) / (count_x - 1),
            (size.y - cell_size * 3 * 12) / 11,
        )

        # chinese weekday key number is the third.
        keyword_num = 0
        if locale.getlocale()[0] == "zh_CN":
            keyword_num = 2
        # first character of localized day names, starting with Monday.
        dow = [
            locale.nl_langinfo(day)[keyword_num].upper()
            for day in [
                locale.DAY_2,
                locale.DAY_3,
                locale.DAY_4,
                locale.DAY_5,
                locale.DAY_6,
                locale.DAY_7,
                locale.DAY_1,
            ]
        ]

        for month in range(1, 13):
            date = datetime.date(year, month, 1)
            y = month - 1
            y_pos = offset.y + (y * 3 + 1) * cell_size + y * spacing.y
            dr.add(
                dr.text(
                    date.strftime("%B"),
                    insert=(offset.x, y_pos - 2),
                    fill=self.poster.colors["text"],
                    alignment_baseline="hanging",
                    style=month_style,
                )
            )

            day_offset = date.weekday()
            while date.month == month:
                x = date.day - 1
                x_pos = offset.x + (day_offset + x) * cell_size + x * spacing.x
                pos = (x_pos + 0.05 * cell_size, y_pos + 1.15 * cell_size)
                dim = (cell_size * 0.9, cell_size * 0.9)
                text_date = date.strftime("%Y-%m-%d")
                if text_date in self.poster.tracks_by_date:
                    tracks = self.poster.tracks_by_date[text_date]
                    length = sum([t.length for t in tracks])
                    has_special = len([t for t in tracks if t.special]) > 0
                    color = self.color(
                        self.poster.length_range_by_date, length, has_special
                    )
                    dr.add(dr.rect(pos, dim, fill=color))
                    dr.add(
                        dr.text(
                            utils.format_float(self.poster.m2u(length)),
                            insert=(
                                pos[0] + cell_size / 2,
                                pos[1] + cell_size + cell_size / 2,
                            ),
                            text_anchor="middle",
                            style=day_length_style,
                            fill=self.poster.colors["text"],
                        )
                    )
                else:
                    dr.add(dr.rect(pos, dim, fill="#444444"))

                dr.add(
                    dr.text(
                        dow[date.weekday()],
                        insert=(
                            offset.x + (day_offset + x) * cell_size + cell_size / 2,
                            pos[1] + cell_size / 2,
                        ),
                        text_anchor="middle",
                        alignment_baseline="middle",
                        style=day_style,
                    )
                )
                date += datetime.timedelta(1)