from datetime import date, timedelta THEMES: dict[str, dict[str, str | list[str]]] = { "light": { "bg": "#ffffff", "text": "#24292f", "muted": "#57606a", "empty": "#ebedf0", "levels": ["#ebedf0", "#9be9a8", "#40c463", "#30a14e", "#216e39"], }, "dark": { "bg": "#0d1117", "text": "#c9d1d9", "muted": "#8b949e", "empty": "#161b22", "levels": ["#161b22", "#0e4429", "#006d32", "#26a641", "#39d353"], }, } def _intensity_level(value: int, max_value: int) -> int: if value <= 0 or max_value <= 0: return 0 ratio = value / max_value if ratio < 0.25: return 1 if ratio < 0.5: return 2 if ratio < 0.75: return 3 return 4 def _build_calendar_days(from_date: date, to_date: date) -> list[date]: days: list[date] = [] current = from_date while current <= to_date: days.append(current) current += timedelta(days=1) return days def render_activity_svg( daily_totals: dict[str, int], from_date: date, to_date: date, days_count: int, total_contributions: int, theme: str, ) -> str: palette = THEMES[theme if theme in THEMES else "light"] levels = palette["levels"] day_size = 11 gap = 3 left_padding = 42 top_padding = 30 month_label_height = 14 grid_top = top_padding + month_label_height start = from_date - timedelta(days=(from_date.weekday() + 1) % 7) end = to_date + timedelta(days=(5 - to_date.weekday()) % 7 + 1) all_days = _build_calendar_days(start, end) week_count = max(1, len(all_days) // 7) grid_width = week_count * (day_size + gap) grid_height = 7 * (day_size + gap) width = left_padding + grid_width + 20 height = grid_top + grid_height + 34 max_value = max(daily_totals.values(), default=0) lines: list[str] = [] lines.append(f'') lines.append(f'') lines.append( f'{total_contributions} contributions in the last {days_count} days' ) month_x_positions: dict[str, int] = {} for idx, day in enumerate(all_days): if day.day == 1: month_x_positions[day.strftime("%b")] = left_padding + (idx // 7) * (day_size + gap) for label, x in month_x_positions.items(): lines.append( f'{label}' ) weekday_labels = {1: "Mon", 3: "Wed", 5: "Fri"} for row, label in weekday_labels.items(): y = grid_top + row * (day_size + gap) + 9 lines.append( f'{label}' ) for idx, day in enumerate(all_days): week = idx // 7 row = (day.weekday() + 1) % 7 x = left_padding + week * (day_size + gap) y = grid_top + row * (day_size + gap) value = daily_totals.get(day.isoformat(), 0) level = _intensity_level(value, max_value) fill = levels[level] lines.append( f'' ) legend_y = grid_top + grid_height + 16 legend_x = left_padding + grid_width - 120 lines.append( f'Less' ) for i, color in enumerate(levels): lx = legend_x + 26 + i * (day_size + 2) lines.append( f'' ) lines.append( f'More' ) lines.append("") return "".join(lines)