Skip to content

Instantly share code, notes, and snippets.

@stranger-danger-zamu
Created September 7, 2022 04:37
Show Gist options
  • Save stranger-danger-zamu/8aa690bed52e8ad5b57aa98339ed4ec9 to your computer and use it in GitHub Desktop.
Save stranger-danger-zamu/8aa690bed52e8ad5b57aa98339ed4ec9 to your computer and use it in GitHub Desktop.
Roughly based off of github.com/blurfx/calendar-heatmap.
from pathlib import Path
from collections import defaultdict
from datetime import datetime
def cmd_freq_by_date(bash_history_path:Path):
freqs = defaultdict(int)
for _, _, dt_str, _ in (l.strip().split(' ', 3) for l in bash_history_path.read_text().splitlines()):
dt = datetime.fromisoformat(dt_str[1:-1])
freqs[(dt.year, dt.month, dt.day)] += 1
return freqs
if __name__ == "__main__":
import os
from datetime import timedelta
from calendar_heatmap import main
# dump bash history to file
# $ HISTTIMEFORMAT="[%FT%T+<your timezome>] " history > $BASH_HISTORY_PATH
bash_history_path = Path(os.environ.get("BASH_HISTORY_PATH", "./test.txt"))
freqs = cmd_freq_by_date(bash_history_path)
main(freqs, Path('/tmp/output.html'), datetime.now()-timedelta(days=365), datetime.now())
from collections import defaultdict, namedtuple
from datetime import datetime, timedelta
from pathlib import Path
from statistics import quantiles
Point = namedtuple("Point", "x y")
DAY_TYPE = MONTH_TYPE = YEAR_TYPE = int
DATE_TYPE = tuple[YEAR_TYPE, MONTH_TYPE, DAY_TYPE]
class CalendarHeatMapConf:
colors: list[str] = ["#161b22", "#0e4429", "#006d32", "#26a641", "#39d353"]
block_size: float = 11
block_roundness: float = 2
block_margin: float = 2
month_labels: list[str] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
weekday_labels: list[str] = ["", "Mon", "", "Wed", "", "Fri", ""]
week_label_width: float = 0
month_label_height: float = 15
class CalendarHeatMap:
DAYS = 7
MONTH_LABEL_FONT_SIZE = 10
WEEK_DAY_LABEL_FONT_SIZE = 9
WEEK_DAY_MAP = {6:0, 0:1, 1:2, 2:3, 3:4, 4:5, 5:6}
RECT_TEMPLATE = "<rect x='{x}' y='{y}' rx='{rx}' ry='{ry}' width='{width}' height='{height}' style='{style}'><title>{date} ({freq})</title></rect>"
TEXT_TEMPLATE = "<text x='{x}' y='{y}' style='font-size: {font_size}px; alignment-baseline: central; fill: #aaa'>{text}</text>"
SVG_HEADER_TEMPLATE = "<svg version='1.1' xmlns='http://www.w3.org/2000/svg' width='{}' height='{}' style='display: block; margin: auto;'>"
SVG_FOOTER_TEMPLATE = '</svg>'
def __init__(self, conf: CalendarHeatMapConf|None=None):
self.config: CalendarHeatMapConf = conf or CalendarHeatMapConf()
def get_position(self, row: int, col: int) -> Point:
bounds = self.config.block_size + self.config.block_margin
return Point(
x = self.config.week_label_width + bounds * row,
y = self.config.month_label_height + bounds * col
)
def count_weeks(self, from_dt: datetime, to_dt: datetime) -> int:
from_time = from_dt
to_timestamp = to_dt
weeks = 0
while from_time <= to_timestamp:
from_time = from_time + timedelta(days=7)
weeks += 1
return weeks
def generate(self, from_dt: datetime, to_dt: datetime, data: dict[DATE_TYPE, int]) -> str:
weeks = self.count_weeks(from_dt, to_dt)
cur_pos = from_dt
prev_month = -1
end_timestamp = to_dt.timestamp()
color_limits = [0, *quantiles(data.values(), n=5)]
colors = dict(zip(color_limits, self.config.colors))
result = []
for s in self.config.weekday_labels:
self.config.week_label_width = max(
self.config.week_label_width,
len(s) * self.WEEK_DAY_LABEL_FONT_SIZE
)
if cur_pos.month != (cur_pos + timedelta(days=7)).month:
prev_month = cur_pos.month
canvas_pos = self.get_position(weeks, self.DAYS)
result.append(self.SVG_HEADER_TEMPLATE.format(canvas_pos.x, canvas_pos.y))
week = 0
y_margin = (self.config.block_size / 2) - self.config.month_label_height
while week < weeks and cur_pos.timestamp() <= end_timestamp:
if cur_pos.weekday() == 6:
week += 1
current_month = cur_pos.month
if prev_month != current_month:
pos = self.get_position(week, 0)
prev_month = current_month
line = self.TEXT_TEMPLATE.format(
x=pos.x,
y=pos.y + y_margin,
text=self.config.month_labels[prev_month-1],
font_size=self.MONTH_LABEL_FONT_SIZE
)
result.append(line)
pos = self.get_position(week, self.WEEK_DAY_MAP[cur_pos.weekday()]-1)
freq = data.get((cur_pos.year, cur_pos.month, cur_pos.day), 0)
color = colors.get(0)
for limit in color_limits:
color = colors.get(limit)
if freq <= limit:
break
fill_color = color
# canvas.roundrect(
rect = self.RECT_TEMPLATE.format(
date=cur_pos.date().isoformat(),
freq=freq,
x=pos.x,
y=pos.y + self.config.month_label_height,
width=self.config.block_size,
height=self.config.block_size,
rx=self.config.block_roundness,
ry=self.config.block_roundness,
style=f"fill:{fill_color}"
)
result.append(rect)
cur_pos += timedelta(days=1)
print("new pos:", cur_pos)
for day in range(self.DAYS):
pos = self.get_position(0, day + 1)
# canvas.Text(
line = self.TEXT_TEMPLATE.format(
x=0,
y=pos.y - (self.config.block_size /2),
text=self.config.weekday_labels[day],
font_size=self.MONTH_LABEL_FONT_SIZE
)
result.append(line)
result.append(self.SVG_FOOTER_TEMPLATE)
return '\n'.join(result)
def main(freqs: dict[DATE_TYPE, int], output_path:Path, start_dt:datetime, end_dt:datetime):
c = CalendarHeatMap()
result = c.generate(start_dt,end_dt, freqs)
result = f"<html><body style='background-color: #0d1117;'><div id='content' style='height: 100%; width: 100%; display:grid; align-content: center;'>{result}</div></body></html>"
output_path.write_text(result)
<html><body style="background-color: #0d1117;"><div id="content" style="height: 100%; width: 100%; display:grid; align-content: center;"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="716" height="106" style="display: block; margin: auto;">
<text x="27" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Sep</text>
<rect x="27" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-07 (0)</title></rect>
<rect x="27" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-08 (0)</title></rect>
<rect x="27" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-09 (0)</title></rect>
<rect x="27" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-10 (0)</title></rect>
<rect x="27" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-11 (0)</title></rect>
<rect x="40" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-12 (0)</title></rect>
<rect x="40" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-13 (0)</title></rect>
<rect x="40" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-14 (0)</title></rect>
<rect x="40" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-15 (0)</title></rect>
<rect x="40" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-16 (0)</title></rect>
<rect x="40" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-17 (0)</title></rect>
<rect x="40" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-18 (0)</title></rect>
<rect x="53" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-19 (0)</title></rect>
<rect x="53" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-20 (0)</title></rect>
<rect x="53" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-21 (0)</title></rect>
<rect x="53" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-22 (0)</title></rect>
<rect x="53" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-23 (0)</title></rect>
<rect x="53" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-24 (0)</title></rect>
<rect x="53" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-25 (0)</title></rect>
<rect x="66" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-26 (0)</title></rect>
<rect x="66" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-27 (0)</title></rect>
<rect x="66" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-28 (0)</title></rect>
<rect x="66" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-29 (0)</title></rect>
<rect x="66" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-09-30 (0)</title></rect>
<text x="66" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Oct</text>
<rect x="66" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-01 (0)</title></rect>
<rect x="66" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-02 (0)</title></rect>
<rect x="79" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-03 (0)</title></rect>
<rect x="79" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-04 (0)</title></rect>
<rect x="79" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-05 (0)</title></rect>
<rect x="79" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-06 (0)</title></rect>
<rect x="79" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-07 (0)</title></rect>
<rect x="79" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-08 (0)</title></rect>
<rect x="79" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-09 (0)</title></rect>
<rect x="92" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-10 (0)</title></rect>
<rect x="92" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-11 (0)</title></rect>
<rect x="92" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-12 (0)</title></rect>
<rect x="92" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-13 (0)</title></rect>
<rect x="92" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-14 (0)</title></rect>
<rect x="92" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-15 (0)</title></rect>
<rect x="92" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-16 (0)</title></rect>
<rect x="105" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-17 (0)</title></rect>
<rect x="105" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-18 (0)</title></rect>
<rect x="105" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-19 (0)</title></rect>
<rect x="105" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-20 (0)</title></rect>
<rect x="105" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-21 (0)</title></rect>
<rect x="105" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-22 (0)</title></rect>
<rect x="105" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-23 (0)</title></rect>
<rect x="118" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-24 (0)</title></rect>
<rect x="118" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-25 (0)</title></rect>
<rect x="118" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-26 (0)</title></rect>
<rect x="118" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-27 (0)</title></rect>
<rect x="118" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-28 (0)</title></rect>
<rect x="118" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-29 (0)</title></rect>
<rect x="118" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-30 (0)</title></rect>
<rect x="131" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-10-31 (0)</title></rect>
<text x="131" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Nov</text>
<rect x="131" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-01 (0)</title></rect>
<rect x="131" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-02 (0)</title></rect>
<rect x="131" y="56" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-03 (0)</title></rect>
<rect x="131" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-04 (0)</title></rect>
<rect x="131" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-05 (0)</title></rect>
<rect x="131" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-06 (0)</title></rect>
<rect x="144" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-07 (0)</title></rect>
<rect x="144" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-11-08 (0)</title></rect>
<rect x="144" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-09 (145)</title></rect>
<rect x="144" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-10 (158)</title></rect>
<rect x="144" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-11 (1460)</title></rect>
<rect x="144" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-12 (667)</title></rect>
<rect x="144" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-13 (439)</title></rect>
<rect x="157" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-14 (461)</title></rect>
<rect x="157" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2021-11-15 (41)</title></rect>
<rect x="157" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-16 (283)</title></rect>
<rect x="157" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-17 (186)</title></rect>
<rect x="157" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-18 (262)</title></rect>
<rect x="157" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2021-11-19 (55)</title></rect>
<rect x="157" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-20 (182)</title></rect>
<rect x="170" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2021-11-21 (13)</title></rect>
<rect x="170" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-11-22 (111)</title></rect>
<rect x="170" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-23 (310)</title></rect>
<rect x="170" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2021-11-24 (14)</title></rect>
<rect x="170" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-25 (459)</title></rect>
<rect x="170" y="82" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2021-11-26 (9)</title></rect>
<rect x="170" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2021-11-27 (5)</title></rect>
<rect x="183" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-11-28 (64)</title></rect>
<rect x="183" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-29 (405)</title></rect>
<rect x="183" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-11-30 (938)</title></rect>
<text x="183" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Dec</text>
<rect x="183" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-01 (1978)</title></rect>
<rect x="183" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-02 (361)</title></rect>
<rect x="183" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-03 (417)</title></rect>
<rect x="183" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-04 (85)</title></rect>
<rect x="196" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-05 (478)</title></rect>
<rect x="196" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-06 (977)</title></rect>
<rect x="196" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-07 (670)</title></rect>
<rect x="196" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-08 (388)</title></rect>
<rect x="196" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-09 (435)</title></rect>
<rect x="196" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-10 (103)</title></rect>
<rect x="196" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-11 (0)</title></rect>
<rect x="209" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-12 (65)</title></rect>
<rect x="209" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2021-12-13 (27)</title></rect>
<rect x="209" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-14 (88)</title></rect>
<rect x="209" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2021-12-15 (43)</title></rect>
<rect x="209" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2021-12-16 (56)</title></rect>
<rect x="209" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-17 (68)</title></rect>
<rect x="209" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-18 (188)</title></rect>
<rect x="222" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-19 (77)</title></rect>
<rect x="222" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2021-12-20 (33)</title></rect>
<rect x="222" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-21 (0)</title></rect>
<rect x="222" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2021-12-22 (4)</title></rect>
<rect x="222" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-23 (0)</title></rect>
<rect x="222" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-24 (0)</title></rect>
<rect x="222" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-25 (0)</title></rect>
<rect x="235" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-26 (0)</title></rect>
<rect x="235" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2021-12-27 (9)</title></rect>
<rect x="235" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2021-12-28 (174)</title></rect>
<rect x="235" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-29 (101)</title></rect>
<rect x="235" y="69" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2021-12-30 (106)</title></rect>
<rect x="235" y="82" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2021-12-31 (0)</title></rect>
<text x="235" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Jan</text>
<rect x="235" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-01 (3)</title></rect>
<rect x="248" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-02 (1)</title></rect>
<rect x="248" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-01-03 (17)</title></rect>
<rect x="248" y="43" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2022-01-04 (0)</title></rect>
<rect x="248" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-05 (5)</title></rect>
<rect x="248" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-06 (4)</title></rect>
<rect x="248" y="82" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-07 (13)</title></rect>
<rect x="248" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-08 (6)</title></rect>
<rect x="261" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-01-09 (49)</title></rect>
<rect x="261" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-10 (3)</title></rect>
<rect x="261" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-01-11 (87)</title></rect>
<rect x="261" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-12 (1)</title></rect>
<rect x="261" y="69" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-01-13 (78)</title></rect>
<rect x="261" y="82" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-14 (1)</title></rect>
<rect x="261" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-15 (293)</title></rect>
<rect x="274" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-01-16 (34)</title></rect>
<rect x="274" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-17 (14)</title></rect>
<rect x="274" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-18 (231)</title></rect>
<rect x="274" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-19 (3)</title></rect>
<rect x="274" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-01-20 (6)</title></rect>
<rect x="274" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-01-21 (20)</title></rect>
<rect x="274" y="95" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2022-01-22 (0)</title></rect>
<rect x="287" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2022-01-23 (0)</title></rect>
<rect x="287" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-24 (217)</title></rect>
<rect x="287" y="43" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-01-25 (30)</title></rect>
<rect x="287" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-26 (154)</title></rect>
<rect x="287" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-01-27 (22)</title></rect>
<rect x="287" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-28 (319)</title></rect>
<rect x="287" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-29 (577)</title></rect>
<rect x="300" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-01-30 (216)</title></rect>
<rect x="300" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-01-31 (95)</title></rect>
<text x="300" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Feb</text>
<rect x="300" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-01 (447)</title></rect>
<rect x="300" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-02 (329)</title></rect>
<rect x="300" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-03 (424)</title></rect>
<rect x="300" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-04 (175)</title></rect>
<rect x="300" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-02-05 (80)</title></rect>
<rect x="313" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-06 (668)</title></rect>
<rect x="313" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-07 (274)</title></rect>
<rect x="313" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-08 (319)</title></rect>
<rect x="313" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-09 (700)</title></rect>
<rect x="313" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-10 (671)</title></rect>
<rect x="313" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-02-11 (99)</title></rect>
<rect x="313" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-12 (199)</title></rect>
<rect x="326" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-13 (297)</title></rect>
<rect x="326" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-14 (142)</title></rect>
<rect x="326" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-15 (376)</title></rect>
<rect x="326" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-02-16 (93)</title></rect>
<rect x="326" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-02-17 (60)</title></rect>
<rect x="326" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-02-18 (75)</title></rect>
<rect x="326" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-19 (335)</title></rect>
<rect x="339" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-20 (270)</title></rect>
<rect x="339" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-02-21 (24)</title></rect>
<rect x="339" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-22 (299)</title></rect>
<rect x="339" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-23 (202)</title></rect>
<rect x="339" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-02-24 (46)</title></rect>
<rect x="339" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-02-25 (19)</title></rect>
<rect x="339" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-02-26 (1)</title></rect>
<rect x="352" y="17" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2022-02-27 (0)</title></rect>
<rect x="352" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-02-28 (134)</title></rect>
<text x="352" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Mar</text>
<rect x="352" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-01 (470)</title></rect>
<rect x="352" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-03-02 (16)</title></rect>
<rect x="352" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-03-03 (34)</title></rect>
<rect x="352" y="82" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-03-04 (5)</title></rect>
<rect x="352" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-03-05 (115)</title></rect>
<rect x="365" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-06 (284)</title></rect>
<rect x="365" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-07 (142)</title></rect>
<rect x="365" y="43" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-03-08 (54)</title></rect>
<rect x="365" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-09 (250)</title></rect>
<rect x="365" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-10 (514)</title></rect>
<rect x="365" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-11 (519)</title></rect>
<rect x="365" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-03-12 (119)</title></rect>
<rect x="378" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-03-13 (1)</title></rect>
<rect x="378" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-03-14 (32)</title></rect>
<rect x="378" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-03-15 (116)</title></rect>
<rect x="378" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-16 (857)</title></rect>
<rect x="378" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-17 (157)</title></rect>
<rect x="378" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-18 (265)</title></rect>
<rect x="378" y="95" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-03-19 (16)</title></rect>
<rect x="391" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-03-20 (111)</title></rect>
<rect x="391" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-21 (679)</title></rect>
<rect x="391" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-22 (423)</title></rect>
<rect x="391" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-23 (244)</title></rect>
<rect x="391" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-24 (313)</title></rect>
<rect x="391" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-25 (252)</title></rect>
<rect x="391" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-26 (293)</title></rect>
<rect x="404" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-27 (183)</title></rect>
<rect x="404" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-28 (130)</title></rect>
<rect x="404" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-29 (264)</title></rect>
<rect x="404" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-03-30 (344)</title></rect>
<rect x="404" y="69" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-03-31 (103)</title></rect>
<text x="404" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Apr</text>
<rect x="404" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-01 (131)</title></rect>
<rect x="404" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-02 (321)</title></rect>
<rect x="417" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-03 (286)</title></rect>
<rect x="417" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-04 (123)</title></rect>
<rect x="417" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-05 (571)</title></rect>
<rect x="417" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-06 (124)</title></rect>
<rect x="417" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-07 (627)</title></rect>
<rect x="417" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-08 (468)</title></rect>
<rect x="417" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-09 (526)</title></rect>
<rect x="430" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-10 (423)</title></rect>
<rect x="430" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-11 (137)</title></rect>
<rect x="430" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-12 (144)</title></rect>
<rect x="430" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-13 (124)</title></rect>
<rect x="430" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-14 (135)</title></rect>
<rect x="430" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-04-15 (34)</title></rect>
<rect x="430" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-16 (309)</title></rect>
<rect x="443" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-17 (67)</title></rect>
<rect x="443" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-18 (148)</title></rect>
<rect x="443" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-19 (452)</title></rect>
<rect x="443" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-04-20 (17)</title></rect>
<rect x="443" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-04-21 (9)</title></rect>
<rect x="443" y="82" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-04-22 (10)</title></rect>
<rect x="443" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-04-23 (8)</title></rect>
<rect x="456" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-04-24 (55)</title></rect>
<rect x="456" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-25 (101)</title></rect>
<rect x="456" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-26 (65)</title></rect>
<rect x="456" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-27 (157)</title></rect>
<rect x="456" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-04-28 (748)</title></rect>
<rect x="456" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-29 (75)</title></rect>
<rect x="456" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-04-30 (68)</title></rect>
<text x="469" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">May</text>
<rect x="469" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-01 (141)</title></rect>
<rect x="469" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-02 (331)</title></rect>
<rect x="469" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-03 (459)</title></rect>
<rect x="469" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-05-04 (123)</title></rect>
<rect x="469" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-05 (55)</title></rect>
<rect x="469" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-06 (208)</title></rect>
<rect x="469" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-07 (182)</title></rect>
<rect x="482" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-05-08 (99)</title></rect>
<rect x="482" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-09 (167)</title></rect>
<rect x="482" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-10 (130)</title></rect>
<rect x="482" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-11 (43)</title></rect>
<rect x="482" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-12 (260)</title></rect>
<rect x="482" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-13 (21)</title></rect>
<rect x="482" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-14 (2)</title></rect>
<rect x="495" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-15 (16)</title></rect>
<rect x="495" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-16 (2)</title></rect>
<rect x="495" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-05-17 (71)</title></rect>
<rect x="495" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-18 (147)</title></rect>
<rect x="495" y="69" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-05-19 (72)</title></rect>
<rect x="495" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-05-20 (429)</title></rect>
<rect x="495" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-21 (7)</title></rect>
<rect x="508" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-22 (32)</title></rect>
<rect x="508" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-23 (21)</title></rect>
<rect x="508" y="43" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-24 (1)</title></rect>
<rect x="508" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-25 (11)</title></rect>
<rect x="508" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-26 (10)</title></rect>
<rect x="508" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-05-27 (91)</title></rect>
<rect x="508" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-28 (14)</title></rect>
<rect x="521" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-05-29 (28)</title></rect>
<rect x="521" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-30 (3)</title></rect>
<rect x="521" y="43" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-05-31 (11)</title></rect>
<text x="521" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Jun</text>
<rect x="521" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-01 (226)</title></rect>
<rect x="521" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-06-02 (9)</title></rect>
<rect x="521" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-03 (233)</title></rect>
<rect x="521" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-06-04 (73)</title></rect>
<rect x="534" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-06-05 (3)</title></rect>
<rect x="534" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-06 (23)</title></rect>
<rect x="534" y="43" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-06-07 (9)</title></rect>
<rect x="534" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-08 (21)</title></rect>
<rect x="534" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-09 (185)</title></rect>
<rect x="534" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-06-10 (68)</title></rect>
<rect x="534" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-11 (246)</title></rect>
<rect x="547" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-12 (213)</title></rect>
<rect x="547" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-06-13 (80)</title></rect>
<rect x="547" y="43" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-14 (24)</title></rect>
<rect x="547" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-06-15 (78)</title></rect>
<rect x="547" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-16 (25)</title></rect>
<rect x="547" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-06-17 (62)</title></rect>
<rect x="547" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-06-18 (9)</title></rect>
<rect x="560" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-19 (40)</title></rect>
<rect x="560" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-20 (27)</title></rect>
<rect x="560" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-21 (131)</title></rect>
<rect x="560" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-22 (27)</title></rect>
<rect x="560" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-06-23 (9)</title></rect>
<rect x="560" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-24 (60)</title></rect>
<rect x="560" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-06-25 (15)</title></rect>
<rect x="573" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-26 (35)</title></rect>
<rect x="573" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-06-27 (250)</title></rect>
<rect x="573" y="43" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-28 (23)</title></rect>
<rect x="573" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-06-29 (20)</title></rect>
<rect x="573" y="69" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2022-06-30 (0)</title></rect>
<text x="573" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Jul</text>
<rect x="573" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-07-01 (249)</title></rect>
<rect x="573" y="95" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-02 (41)</title></rect>
<rect x="586" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-03 (6)</title></rect>
<rect x="586" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-04 (16)</title></rect>
<rect x="586" y="43" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-05 (54)</title></rect>
<rect x="586" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-06 (40)</title></rect>
<rect x="586" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-07 (41)</title></rect>
<rect x="586" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-08 (37)</title></rect>
<rect x="586" y="95" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-09 (41)</title></rect>
<rect x="599" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-10 (8)</title></rect>
<rect x="599" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-11 (52)</title></rect>
<rect x="599" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-07-12 (77)</title></rect>
<rect x="599" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-13 (5)</title></rect>
<rect x="599" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-07-14 (282)</title></rect>
<rect x="599" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-15 (45)</title></rect>
<rect x="599" y="95" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-07-16 (197)</title></rect>
<rect x="612" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-17 (48)</title></rect>
<rect x="612" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-07-18 (28)</title></rect>
<rect x="612" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-07-19 (64)</title></rect>
<rect x="612" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-07-20 (110)</title></rect>
<rect x="612" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-21 (11)</title></rect>
<rect x="612" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-07-22 (173)</title></rect>
<rect x="612" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-07-23 (104)</title></rect>
<rect x="625" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-07-24 (172)</title></rect>
<rect x="625" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-07-25 (65)</title></rect>
<rect x="625" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-07-26 (161)</title></rect>
<rect x="625" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-27 (15)</title></rect>
<rect x="625" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-28 (11)</title></rect>
<rect x="625" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-07-29 (89)</title></rect>
<rect x="625" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-30 (14)</title></rect>
<rect x="638" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-07-31 (15)</title></rect>
<text x="638" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Aug</text>
<rect x="638" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-01 (14)</title></rect>
<rect x="638" y="43" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-02 (13)</title></rect>
<rect x="638" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-08-03 (48)</title></rect>
<rect x="638" y="69" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-04 (12)</title></rect>
<rect x="638" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-05 (69)</title></rect>
<rect x="638" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-06 (79)</title></rect>
<rect x="651" y="17" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-07 (7)</title></rect>
<rect x="651" y="30" rx="2" ry="2" width="11" height="11" style="fill:#161b22"><title>2022-08-08 (0)</title></rect>
<rect x="651" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-08-09 (380)</title></rect>
<rect x="651" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-10 (96)</title></rect>
<rect x="651" y="69" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-08-11 (16)</title></rect>
<rect x="651" y="82" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-08-12 (27)</title></rect>
<rect x="651" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-13 (2)</title></rect>
<rect x="664" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-14 (80)</title></rect>
<rect x="664" y="30" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-08-15 (33)</title></rect>
<rect x="664" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-08-16 (130)</title></rect>
<rect x="664" y="56" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-08-17 (18)</title></rect>
<rect x="664" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-08-18 (140)</title></rect>
<rect x="664" y="82" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-19 (9)</title></rect>
<rect x="664" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-20 (11)</title></rect>
<rect x="677" y="17" rx="2" ry="2" width="11" height="11" style="fill:#006d32"><title>2022-08-21 (44)</title></rect>
<rect x="677" y="30" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-22 (97)</title></rect>
<rect x="677" y="43" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-23 (2)</title></rect>
<rect x="677" y="56" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-24 (5)</title></rect>
<rect x="677" y="69" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-25 (61)</title></rect>
<rect x="677" y="82" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-26 (90)</title></rect>
<rect x="677" y="95" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-27 (83)</title></rect>
<rect x="690" y="17" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-08-28 (234)</title></rect>
<rect x="690" y="30" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-08-29 (12)</title></rect>
<rect x="690" y="43" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-30 (76)</title></rect>
<rect x="690" y="56" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-08-31 (116)</title></rect>
<text x="690" y="5.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Sep</text>
<rect x="690" y="69" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-09-01 (337)</title></rect>
<rect x="690" y="82" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-09-02 (654)</title></rect>
<rect x="690" y="95" rx="2" ry="2" width="11" height="11" style="fill:#0e4429"><title>2022-09-03 (1)</title></rect>
<rect x="703" y="17" rx="2" ry="2" width="11" height="11" style="fill:#26a641"><title>2022-09-04 (95)</title></rect>
<rect x="703" y="30" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-09-05 (144)</title></rect>
<rect x="703" y="43" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-09-06 (244)</title></rect>
<rect x="703" y="56" rx="2" ry="2" width="11" height="11" style="fill:#39d353"><title>2022-09-07 (688)</title></rect>
<text x="0" y="22.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa"></text>
<text x="0" y="35.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Mon</text>
<text x="0" y="48.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa"></text>
<text x="0" y="61.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Wed</text>
<text x="0" y="74.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa"></text>
<text x="0" y="87.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa">Fri</text>
<text x="0" y="100.5" style="font-size: 10px; alignment-baseline: central; fill: #aaa"></text>
</svg></div></body></html>
@stranger-danger-zamu
Copy link
Author

Found atuin. It looked cool but saw that pretty graphs were only for the hosted service.

So instead of using the hosted service (which is probably fine), I rolled a generic version that can create a frequency-based calendar heatmap from any data set that is passed in as dict[DATE_TYPE, int] where DATE_TYPE = tuple[int,int,int].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment